#include "stdafx.h"
#include "font.h"
#include "texture.h"

#pragma warning(disable : 4996)



GLFont::GLFont(const char* fontname)
:	m_width(16),
	m_height(16),
	m_spacing(10),
	m_texture(0),
	m_base(0),
	m_initialized(false)
{
	BuildFont(fontname);
}



GLFont::~GLFont()
{
	KillFont();
}



/*
 *	Some operations that need to be done once, just before printing text
 *	After printing, we have to call PrintEnd
 *	Between PrintBegin and PrintEnd we can call Print many times
 */
void GLFont::PrintBegin()
{
	//
	// if not initialized already, init now with default fontname
	if(!m_initialized)
		BuildFont();

	//
	// we enable/disable some things here, so push current state
	// so we can restore it in PrintEnd()
	glPushAttrib(GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT);				

	ASSERT(glIsTexture(m_texture));
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D,m_texture);		// Select Our Font Texture

	glDisable(GL_DEPTH_TEST);
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();								// Store The Projection Matrix
	glLoadIdentity();							// Reset The Projection Matrix
	glOrtho(0,800,0,600,-1,1);					// Set Up An Ortho Screen
	glMatrixMode(GL_MODELVIEW);					// Select The Modelview Matrix
	glPushMatrix();								// Store The Modelview Matrix

	glDisable(GL_LIGHTING);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE);
	//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_COLOR);
	
	glColor3f(1,1,1);
}

/*
 *	print in specified position, with specified set (normal/italic)
 */
void GLFont::Print(int x,int y,enumFontSet set,char *text,...)
{
    char buffer[256];
	va_list arglist;
	va_start(arglist,text);
	vsprintf(buffer,text,arglist);
	va_end(arglist);

	glLoadIdentity();							// Reset The Modelview Matrix
	glTranslated(x,y,0);						// Position The Text (0,0 - Bottom Left)
	glListBase(m_base-32+(128*set));			// Choose The Font Set (0 or 1)
	glCallLists((GLsizei)strlen(buffer),GL_BYTE,buffer);	// Write The Text To The Screen
}

/*
 *	here we restore any changes made in PrintBegin	
 */
void GLFont::PrintEnd()
{
	glMatrixMode(GL_PROJECTION);				// Select The Projection Matrix
	glPopMatrix();								// Restore The Old Projection Matrix
	glMatrixMode(GL_MODELVIEW);					// Select The Modelview Matrix
	glPopMatrix();								// Restore The Old Projection Matrix
	glEnable(GL_DEPTH_TEST);					// Enables Depth Testing

	glPopAttrib();
}


/*
 *	Kill the font
 *	delete display lists, release font, set as un-initialized
 */
void GLFont::KillFont()
{
	glDeleteLists(m_base,256);
	glDeleteTextures(1,&m_texture);
	m_initialized=false;
}

/*
 *	Load a texture that contains the letters
 *	Build 256 display lists, one for each letters
 *	Each letter is a quad, mapped to the corresponding letter in the texture
 */
bool GLFont::BuildFont(const char* fontname)
{
	m_initialized=false;
	m_texture = LoadTexture(fontname);
	if(!glIsTexture(m_texture))
	{
		Log("GLFont::BuildFont: could not create texture %s",fontname);
		return false;
	}

	float cx;
	float cy;
	float weightx(float(1.0f/m_width));
	float weighty(float(1.0f/m_height));
	
	//
	// generate 256 empty display lists
	m_base = glGenLists(256);
	//
	// Select Our Font Texture
	glBindTexture(GL_TEXTURE_2D, m_texture);

	for(int loop=0; loop<256; loop++)
	{
		cx=float(loop%16)*weightx;				// X Position Of Current Character;
		cy=float(loop/16)*weighty;				// Y Position Of Current Character
		
		glNewList(m_base+loop,GL_COMPILE);		// Start Building A List
		{
			glBegin(GL_QUADS);						// Use A Quad For Each Character
			{
				glTexCoord2f(cx,1-cy-weighty);			// Tex Coord (Bottom Left)
				glVertex2i(0,0);						// Ver Coord (Bottom Left)
				glTexCoord2f(cx+weightx,1-cy-weighty);	// Tex Coord (Bottom Right)
				glVertex2i(m_width,0);					// Ver Coord (Bottom Right)
				glTexCoord2f(cx+weightx,1-cy);			// Tex Coord (Top Right)
				glVertex2i(m_width,m_height);			// Ver Coord (Top Right)
				glTexCoord2f(cx,1-cy);					// Tex Coord (Top Left)
				glVertex2i(0,m_height);					// Ver Coord (Top Left)
			}
			glEnd();									// Done Building Quad (Char)
			glTranslated(m_spacing,0,0);				// Move To The Right Of 
														// The Character
		}
		glEndList();									// Done Building The 
														// Display List
	}

	m_initialized=true;
	return m_initialized;
}


